Repository navigation
Conversation
…a body A 204 response ends at the first empty line after its header fields regardless of the fields present (RFC 9112 section 6.3), and a server must not send Transfer-Encoding or Content-Length with it (RFC 9112 section 6.1, RFC 9110 section 8.6). The client already reads no body after a 204, and it refuses to reuse the connection when extra bytes are found in the read buffer or on the idle connection in the pool. Body bytes that a non-conformant server sends after the connection has been handed to the next request escape those checks: they are parsed as the response to that request, and every later response on the connection is attributed to the wrong request. Treat Transfer-Encoding or a non-zero Content-Length on a 204 as the signal that the server may still send a body, and disable keep-alive for that session in respect_keepalive(). Conformant servers are unaffected, and a 204 with Content-Length: 0 keeps the connection reusable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refuse to reuse an HTTP/1 upstream connection after a
204 No Contentresponse that carriesTransfer-Encodingor a non-zeroContent-Length.Why
A 204 is terminated by the first empty line after its header fields regardless of the fields present (RFC 9112 §6.3), and a server MUST NOT send
Transfer-EncodingorContent-Lengthwith it (RFC 9112 §6.1, RFC 9110 §8.6). The client correctly reads no body after a 204, and it already refuses to reuse a connection when extra bytes are found in the read buffer or on the idle connection in the pool.Those checks can only see bytes that have already arrived. If a non-conformant server sends the body it announced after the connection has been handed to the next request, that request parses those bytes as its response, and every later response on the connection is attributed to the wrong request.
On a 204 the two header fields are a free, precise signal of that server behaviour, so this change treats them as "the server may still send a body" and disables keep-alive for the session in
respect_keepalive(). Conformant servers are unaffected; a 204 withContent-Length: 0, which is common in practice and announces no body, keeps the connection reusable.Responses to
HEADrequests and304responses may legitimately carry these fields as metadata, so they are intentionally left unchanged.Tests
protocols::http::v1::client: a 204 withContent-Length: 128,Content-Length: 1,Transfer-Encoding: chunked, orTransfer-Encoding: chunkedplusContent-Length: 0is still read as bodyless, disables keep-alive even withConnection: keep-alive, andreuse()returnsNone. A 204 with no framing fields or withContent-Length: 0stays reusable.connectors::http::v1: against a loopback server that sends only the header section of a 204 withContent-Length: 128orTransfer-Encoding: chunked, the released session is not returned to the pool. WithContent-Length: 0it is.The six cases that frame a body fail on
mainand pass with this change.cargo fmt --check,cargo clippy -p pingora-core --all-targets -- --deny=warnings, and the HTTP/1 protocol and connector test modules pass locally.